package io.github.echarts.model.geometry;

import java.util.Arrays;
import java.util.Objects;

/**
 * 表示线条的样式
 * 包括线宽、颜色、线型、虚线模式等属性
 */
public class LineStyle {
    
    /**
     * 线型枚举
     */
    public enum LineType {
        /**
         * 实线
         */
        SOLID,
        
        /**
         * 虚线
         */
        DASHED,
        
        /**
         * 点线
         */
        DOTTED
    }
    
    /**
     * 线端样式枚举
     */
    public enum LineCap {
        /**
         * 平头结束（默认）
         */
        BUTT,
        
        /**
         * 圆头结束
         */
        ROUND,
        
        /**
         * 方头结束（超出实际路径）
         */
        SQUARE
    }
    
    /**
     * 线条连接样式枚举
     */
    public enum LineJoin {
        /**
         * 尖角连接（默认）
         */
        MITER,
        
        /**
         * 圆角连接
         */
        ROUND,
        
        /**
         * 斜角连接
         */
        BEVEL
    }
    
    /**
     * 默认线宽
     */
    public static final double DEFAULT_WIDTH = 1.0;
    
    /**
     * 默认线型
     */
    public static final LineType DEFAULT_TYPE = LineType.SOLID;
    
    /**
     * 默认线端样式
     */
    public static final LineCap DEFAULT_CAP = LineCap.BUTT;
    
    /**
     * 默认线条连接样式
     */
    public static final LineJoin DEFAULT_JOIN = LineJoin.MITER;
    
    /**
     * 默认线条颜色
     */
    public static final Color DEFAULT_COLOR = Color.BLACK;
    
    /**
     * 线宽
     */
    private final double width;
    
    /**
     * 线条颜色
     */
    private final Color color;
    
    /**
     * 线型
     */
    private final LineType type;
    
    /**
     * 线端样式
     */
    private final LineCap cap;
    
    /**
     * 线条连接样式
     */
    private final LineJoin join;
    
    /**
     * 自定义虚线模式，仅当type为DASHED或DOTTED时有效
     * 数组中的值表示交替的线段长度和间隙长度，如[5, 10, 2, 5]表示5像素线段，10像素间隙，2像素线段，5像素间隙，然后重复
     */
    private final double[] dashPattern;
    
    /**
     * 创建默认线条样式（黑色实线，宽度为1.0）
     */
    public LineStyle() {
        this(DEFAULT_WIDTH, DEFAULT_COLOR, DEFAULT_TYPE, DEFAULT_CAP, DEFAULT_JOIN, null);
    }
    
    /**
     * 根据颜色创建线条样式，使用默认的其他属性
     * 
     * @param color 线条颜色
     */
    public LineStyle(Color color) {
        this(DEFAULT_WIDTH, color, DEFAULT_TYPE, DEFAULT_CAP, DEFAULT_JOIN, null);
    }
    
    /**
     * 根据线宽和颜色创建线条样式，使用默认的其他属性
     * 
     * @param width 线宽
     * @param color 线条颜色
     */
    public LineStyle(double width, Color color) {
        this(width, color, DEFAULT_TYPE, DEFAULT_CAP, DEFAULT_JOIN, null);
    }
    
    /**
     * 根据线宽、颜色和线型创建线条样式
     * 
     * @param width 线宽
     * @param color 线条颜色
     * @param type 线型
     */
    public LineStyle(double width, Color color, LineType type) {
        this(width, color, type, DEFAULT_CAP, DEFAULT_JOIN, null);
    }
    
    /**
     * 创建线条样式
     * 
     * @param width 线宽
     * @param color 线条颜色
     * @param type 线型
     * @param cap 线端样式
     * @param join 线条连接样式
     * @param dashPattern 自定义虚线模式，仅当type为DASHED或DOTTED时有效
     */
    public LineStyle(double width, Color color, LineType type, LineCap cap, LineJoin join, double[] dashPattern) {
        this.width = width > 0 ? width : DEFAULT_WIDTH;
        this.color = color != null ? color : DEFAULT_COLOR;
        this.type = type != null ? type : DEFAULT_TYPE;
        this.cap = cap != null ? cap : DEFAULT_CAP;
        this.join = join != null ? join : DEFAULT_JOIN;
        
        // 只有在类型为DASHED或DOTTED时，才使用自定义虚线模式
        if (dashPattern != null && dashPattern.length > 0 && (this.type == LineType.DASHED || this.type == LineType.DOTTED)) {
            this.dashPattern = Arrays.copyOf(dashPattern, dashPattern.length);
        } else {
            // 根据线型创建默认的虚线模式
            switch (this.type) {
                case DASHED:
                    this.dashPattern = new double[]{this.width * 4, this.width * 2};
                    break;
                case DOTTED:
                    this.dashPattern = new double[]{this.width, this.width * 2};
                    break;
                default:
                    this.dashPattern = null;
            }
        }
    }
    
    /**
     * 获取线宽
     * 
     * @return 线宽
     */
    public double getWidth() {
        return width;
    }
    
    /**
     * 获取线条颜色
     * 
     * @return 线条颜色
     */
    public Color getColor() {
        return color;
    }
    
    /**
     * 获取线型
     * 
     * @return 线型
     */
    public LineType getType() {
        return type;
    }
    
    /**
     * 获取线端样式
     * 
     * @return 线端样式
     */
    public LineCap getCap() {
        return cap;
    }
    
    /**
     * 获取线条连接样式
     * 
     * @return 线条连接样式
     */
    public LineJoin getJoin() {
        return join;
    }
    
    /**
     * 获取自定义虚线模式
     * 
     * @return 自定义虚线模式，如果为实线或未设置自定义模式则返回null
     */
    public double[] getDashPattern() {
        return dashPattern != null ? Arrays.copyOf(dashPattern, dashPattern.length) : null;
    }
    
    /**
     * 检查是否为虚线样式（包括虚线和点线）
     * 
     * @return 如果是虚线样式返回true，否则返回false
     */
    public boolean isDashed() {
        return type == LineType.DASHED || type == LineType.DOTTED;
    }
    
    /**
     * 创建一个新的LineStyle，使用新的线宽
     * 
     * @param width 新的线宽
     * @return 新的LineStyle对象
     */
    public LineStyle withWidth(double width) {
        return new LineStyle(width, this.color, this.type, this.cap, this.join, this.dashPattern);
    }
    
    /**
     * 创建一个新的LineStyle，使用新的颜色
     * 
     * @param color 新的颜色
     * @return 新的LineStyle对象
     */
    public LineStyle withColor(Color color) {
        return new LineStyle(this.width, color, this.type, this.cap, this.join, this.dashPattern);
    }
    
    /**
     * 创建一个新的LineStyle，使用新的线型
     * 
     * @param type 新的线型
     * @return 新的LineStyle对象
     */
    public LineStyle withType(LineType type) {
        return new LineStyle(this.width, this.color, type, this.cap, this.join, null);
    }
    
    /**
     * 创建一个新的LineStyle，使用新的线端样式
     * 
     * @param cap 新的线端样式
     * @return 新的LineStyle对象
     */
    public LineStyle withCap(LineCap cap) {
        return new LineStyle(this.width, this.color, this.type, cap, this.join, this.dashPattern);
    }
    
    /**
     * 创建一个新的LineStyle，使用新的线条连接样式
     * 
     * @param join 新的线条连接样式
     * @return 新的LineStyle对象
     */
    public LineStyle withJoin(LineJoin join) {
        return new LineStyle(this.width, this.color, this.type, this.cap, join, this.dashPattern);
    }
    
    /**
     * 创建一个新的LineStyle，使用新的虚线模式
     * 
     * @param dashPattern 新的虚线模式
     * @return 新的LineStyle对象
     */
    public LineStyle withDashPattern(double[] dashPattern) {
        // 如果是实线类型但尝试设置虚线模式，则自动切换为虚线类型
        LineType newType = this.type;
        if (this.type == LineType.SOLID && dashPattern != null && dashPattern.length > 0) {
            newType = LineType.DASHED;
        }
        return new LineStyle(this.width, this.color, newType, this.cap, this.join, dashPattern);
    }
    
    /**
     * 获取CSS样式字符串表示
     * 
     * @return CSS样式字符串
     */
    public String toCssString() {
        StringBuilder css = new StringBuilder();
        
        css.append("stroke-width: ").append(width).append(";");
        css.append("stroke: ").append(color.toCssString()).append(";");
        
        // 线端样式
        css.append("stroke-linecap: ");
        switch (cap) {
            case BUTT:
                css.append("butt");
                break;
            case ROUND:
                css.append("round");
                break;
            case SQUARE:
                css.append("square");
                break;
        }
        css.append(";");
        
        // 线条连接样式
        css.append("stroke-linejoin: ");
        switch (join) {
            case MITER:
                css.append("miter");
                break;
            case ROUND:
                css.append("round");
                break;
            case BEVEL:
                css.append("bevel");
                break;
        }
        css.append(";");
        
        // 虚线模式
        if (isDashed() && dashPattern != null && dashPattern.length > 0) {
            css.append("stroke-dasharray: ");
            for (int i = 0; i < dashPattern.length; i++) {
                if (i > 0) css.append(" ");
                css.append(dashPattern[i]);
            }
            css.append(";");
        }
        
        return css.toString();
    }
    
    /**
     * 获取SVG属性表示
     * 
     * @return SVG属性映射
     */
    public String toSvgAttributes() {
        StringBuilder attrs = new StringBuilder();
        
        attrs.append("stroke-width=\"").append(width).append("\" ");
        attrs.append("stroke=\"").append(color.toHexString(true)).append("\" ");
        
        // 线端样式
        attrs.append("stroke-linecap=\"");
        switch (cap) {
            case BUTT:
                attrs.append("butt");
                break;
            case ROUND:
                attrs.append("round");
                break;
            case SQUARE:
                attrs.append("square");
                break;
        }
        attrs.append("\" ");
        
        // 线条连接样式
        attrs.append("stroke-linejoin=\"");
        switch (join) {
            case MITER:
                attrs.append("miter");
                break;
            case ROUND:
                attrs.append("round");
                break;
            case BEVEL:
                attrs.append("bevel");
                break;
        }
        attrs.append("\" ");
        
        // 虚线模式
        if (isDashed() && dashPattern != null && dashPattern.length > 0) {
            attrs.append("stroke-dasharray=\"");
            for (int i = 0; i < dashPattern.length; i++) {
                if (i > 0) attrs.append(" ");
                attrs.append(dashPattern[i]);
            }
            attrs.append("\" ");
        }
        
        return attrs.toString().trim();
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        
        LineStyle lineStyle = (LineStyle) o;
        
        if (Double.compare(lineStyle.width, width) != 0) return false;
        if (!Objects.equals(color, lineStyle.color)) return false;
        if (type != lineStyle.type) return false;
        if (cap != lineStyle.cap) return false;
        if (join != lineStyle.join) return false;
        return Arrays.equals(dashPattern, lineStyle.dashPattern);
    }
    
    @Override
    public int hashCode() {
        int result;
        long temp;
        temp = Double.doubleToLongBits(width);
        result = (int) (temp ^ (temp >>> 32));
        result = 31 * result + (color != null ? color.hashCode() : 0);
        result = 31 * result + (type != null ? type.hashCode() : 0);
        result = 31 * result + (cap != null ? cap.hashCode() : 0);
        result = 31 * result + (join != null ? join.hashCode() : 0);
        result = 31 * result + Arrays.hashCode(dashPattern);
        return result;
    }
    
    @Override
    public String toString() {
        return "LineStyle{" +
                "width=" + width +
                ", color=" + color +
                ", type=" + type +
                ", cap=" + cap +
                ", join=" + join +
                ", dashPattern=" + Arrays.toString(dashPattern) +
                '}';
    }
} 